<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>摹图3D模型</title>
    <!-- 引入 Vue -->
    <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
    <!-- 引入 Element UI CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css">
    <!-- 引入 Element UI JavaScript -->
    <script src="https://unpkg.com/element-ui@2.15.14/lib/index.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            background-color: #000;
            color: #fff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }

        .container {
            display: flex;
            min-height: 100vh;
        }

        .sidebar {
            width: 200px;
            background-color: #1a1a1a;
            padding: 20px;
        }

        .logo {
            margin-bottom: 30px;
        }

        .logo img {
            width: 120px;
        }

        .menu-item {
            padding: 12px;
            color: #fff;
            text-decoration: none;
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            border-radius: 6px;
        }

        .menu-item:hover {
            background-color: #333;
        }

        .menu-item i {
            margin-right: 10px;
        }

        .main-content {
            flex: 1;
            padding: 20px;
        }

        .header {
            display: flex;
            justify-content: flex-end;
            align-items: center;
            margin-bottom: 30px;
        }

        .credits {
            margin-right: 20px;
            padding: 8px 16px;
            background-color: #333;
            border-radius: 20px;
        }

        .model-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
            gap: 20px;
            margin-bottom: 40px;
        }

        .model-card {
            background-color: #1a1a1a;
            border-radius: 8px;
            overflow: hidden;
            aspect-ratio: 1;
        }

        model-viewer {
            width: 100%;
            height: 100%;
            background-color: #000;
        }

        .model-grid {
            position: relative;
            overflow: hidden;
        }

        .model-card-container {
            display: flex;
            overflow-x: hidden;
            scroll-behavior: smooth;
        }

        .model-card {
            flex: 0 0 auto;
            width: 320;
            height: 320;
            margin-right: 10px;
        }

        .model-card {
            transition: box-shadow 0.3s ease-in-out, background-color 0.3s ease-in-out;
        }

        .highlight {
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
            background-color: rgba(200, 200, 200, 0.38); /* 浅灰色背景 */
        }

        .pagination-container {
            display: flex;
            justify-content: center;
            margin-top: 20px; /* 调整上边距 */
        }


        .no-data {
            text-align: center;
            font-size: 18px;
            color: gray;
            margin-top: 20px;
        }



    </style>
    <script src="./public/js/three/three.min.js"></script>
    <script src="./public/js/three/OrbitControls.js"></script>
    <script src="./public/js/three/GLTFLoader.js"></script>
</head>
<body>
<div class="container" id="app1">
    <div class="sidebar">
        <div class="logo">
            <img src="public/logo.png" alt="Logo">
        </div>
        <a href="index.html" class="menu-item">
            <i>🏠</i>
            首页
        </a>
        <a href="indexMy.html" class="menu-item">
            <i>📁</i>
            我的模型
        </a>
    </div>

    <div class="main-content">
        <div class="header">
            <div class="credits">
                <span>💰 {{yue}}</span>
            </div>
            <div class="credits" style="cursor:pointer" @click="chongzhi">
                <span>充值</span>
            </div>
            <div class="credits" style="cursor:pointer" @click="exit">
                <span>切换账号</span>
            </div>
        </div>

        <div class="model-grid" v-if="cs && models.length > 0">
            <div class="model-card-container " style="cursor: pointer;" v-for="(model, index) in models" :key="index" @mouseover="highlight(index)" @mouseleave="removeHighlight(index)">
                <div class="model-card" :class="{'highlight': highlightedIndex === index}">
                    <canvas ref="canvas" :id="'canvas' + index" style="width: 100%; height: 100%;"
                            @click="openModelInNewTab('indexShow.html',model.link)"></canvas>
                </div>
            </div>
        </div>
        <div v-else class="no-data">暂无数据</div>
        <div class="pagination-container">
            <el-pagination
                    v-if="models.length>0"
                    background
                    layout="total, prev, pager, next, jumper"
                    :total="totalRecords"
                    :page-size="pageSize"
                    :current-page="currentPage"
                    @size-change="handleSizeChange"
                    @current-change="handlePageChange">
            </el-pagination>
        </div>


        <el-dialog :visible.sync="chongzhiVisible" width="50%" title="充值">
            <div style="font-weight: bolder;text-align: center;font-size: 20px">请扫码联系服务人员</div>
            <div style="text-align: center;">
                <el-image
                        src="public/lx.png"
                        alt="Logo"
                        style="max-width: 40%; height: auto;">
                </el-image>
            </div>
        </el-dialog>

    </div>
</div>

<script>
    new Vue({
        el: '#app1',
        data() {
            return {
                models: [],
                yue: localStorage.yue,
                chongzhiVisible: false,
                highlightedIndex:null,
                currentPage: 1, // 当前页码
                pageSize: 12, // 每页显示的模型数量
                totalRecords: 0, // 总数据条数
                cs:true,
                loadingInstance:'',
            };
        },
        mounted() {
            this.startLoading();
            this.initData();
        },
        methods: {
            startLoading() {
                this.loadingInstance = this.$loading({
                    text: "加载中，请稍等~",
                    lock: true,
                    spinner: "el-icon-loading",
                    background: "rgba(0, 0, 0, 1)"
                });
            },
            stopLoading() {
                if (this.loadingInstance) {
                    this.loadingInstance.close();
                }
            },
            async initData() {
                try {
                    const response = await fetch(`http://117.131.189.172:8105/api/tasks?page=${this.currentPage}&pageSize=${this.pageSize}&user=${localStorage.username}`);
                    const  data = await response.json();
                    this.totalRecords = data.totalRecords; // 设置总数据条数


                    if (data.tasks.length !== 0) {
                        // 利用 map 方法构造 models 数组
                        this.models = data.tasks.map((task, i) => {
                            return {
                                name: 'Model' + i,
                                link: task.status === 'completed'
                                    ? `http://117.131.189.172:8105/get-glb-file/${task.id}`
                                    : './moxing/loading.glb'
                            };
                        });
                        // 并发加载所有模型
                        await this.loadModels();
                    }else {
                        this.stopLoading();
                    }
                } catch (error) {
                    console.error('初始化数据出错：', error);
                }
            },
            highlight(index) {
                this.highlightedIndex = index;
            },
            removeHighlight(index) {
                if (this.highlightedIndex === index) {
                    this.highlightedIndex = null;
                }
            },
            async handlePageChange(page) {
                this.startLoading();
                this.cs=false;
                setTimeout(()=>{
                    this.cs=true;
                    this.currentPage = page;
                     this.initData();
                },500)

            },
            async handleSizeChange(size) {
                this.startLoading();
                this.pageSize = size;
                this.currentPage = 1; // 改变每页数量时，重置到第一页
                await this.initData();
            },
            loadModels() {
                let that=this;
                setTimeout(async () => {
                    await Promise.all(
                        this.models.map((model, index) => this.loadGLBModel(model.link, index))
                    );
                }, 1000)



                setTimeout(()=>{
                    that.stopLoading();
                },5000)
            },
            loadGLBModel(modelPath, index) {
                const canvas = this.$refs.canvas[index];
                const scene = new THREE.Scene();
                scene.background = null;
                const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);
                const renderer = new THREE.WebGLRenderer({canvas: canvas , alpha: true,antialias: true});
                renderer.setSize(canvas.clientWidth, canvas.clientHeight);
                renderer.setClearColor(0x000000, 0);
                renderer.setPixelRatio(window.devicePixelRatio);



                // 设置渲染器的色调映射
                renderer.toneMapping = THREE.ACESFilmicToneMapping;
                renderer.toneMappingExposure = 1;
                renderer.outputEncoding = THREE.sRGBEncoding;

                // 加载模型
                const loader = new THREE.GLTFLoader();
                loader.load(
                    modelPath,
                    (gltf) => {
                        const model = gltf.scene;

                        // 替换所有网格的材质为 MeshBasicMaterial，实现不受光照影响的“自发光”效果
                        model.traverse((node) => {
                            if (node.isMesh) {
                                const originalMat = node.material;
                                // 如果模型使用贴图，则在新材质中保留贴图
                                if (originalMat.map) {
                                    node.material = new THREE.MeshBasicMaterial({
                                        map: originalMat.map,
                                        color: originalMat.color,
                                        // 如果原材质中有透明度、透明度测试等属性，可根据需要补充
                                        transparent: originalMat.transparent,
                                        opacity: originalMat.opacity
                                    });
                                } else {
                                    node.material = new THREE.MeshBasicMaterial({
                                        color: originalMat.color
                                    });
                                }
                            }
                        });

                        // 计算模型的边界框
                        const box = new THREE.Box3().setFromObject(model);
                        const size = new THREE.Vector3();
                        box.getSize(size);

                        // 缩放模型到适合大小
                        const scale = (1 / Math.max(size.x, size.y, size.z)) * 2.5; // 放大比例
                        model.scale.set(scale, scale, scale);

                        // 调整模型位置到中心
                        const center = new THREE.Vector3();
                        box.getCenter(center);
                        model.position.sub(center);

                        scene.add(model);

                        camera.position.z = size.z * 2 * 1.5; // 增大相机距离
                        animate();
                    },
                    (progress) => {
                        console.log(`Loading progress: ${(progress.loaded / progress.total) * 100}%`);
                    },
                    (error) => {
                        console.error(error);
                    }
                );

                // 添加 OrbitControls
                const controls = new THREE.OrbitControls(camera, renderer.domElement);

                controls.enableZoom = false;   // 禁用缩放
                controls.enableRotate = false; // 禁用旋转
                controls.enablePan = false;    // 禁用平移
                // 如无需要平滑惯性可关闭阻尼
                controls.enableDamping = false;


                // controls.enableDamping = true;
                controls.dampingFactor = 0.1;
                controls.target.set(0, 0.5, 0);





                controls.update();

                // 动画渲染循环
                function animate() {
                    requestAnimationFrame(animate);
                    controls.update(); // 更新控制器
                    renderer.render(scene, camera);
                }
            },

            openModelInNewTab(modelLink, link) {
                if (link.indexOf('loading') != -1) {
                    this.$message.warning('生成中，请稍等');
                    return false;
                }
                localStorage.glbUrl = link;
                window.open(modelLink, '_blank');
            },

            async exit() {
                // 构建确认消息
                const message = `是否退出？`;
                // 弹出确认对话框
                const confirm = await this.$confirm(message, '确认操作', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).catch(err => err);

                if (confirm === 'confirm') {
                    localStorage.token = ''
                    window.location.href = 'index.html';
                }

            },
            async chongzhi() {
                this.chongzhiVisible = true;
            },
        }
    });
</script>
</body>
</html>
